#include "SonixCamera.h"
#include "LUOptDev.h"
#include "util.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

BOOL camera_init = FALSE;
extern ERROR_CODE gEC;
extern unsigned int uiRomID;

bool SonixCam_Init(char *vidpid)
{
	fprintf(stdout,"---SonixCam_Init---\n");
    if(camera_init)
        return TRUE;

	if (libusb_init(NULL) < 0)
 	{
		fprintf(stderr, "failed to initialise libusb\n");
		return FALSE;
	}

    if(TRUE != LibUsb_EnumDevice(vidpid))
    {
        gEC = EC_NoFindDevice;
		return FALSE;
    }
    camera_init = TRUE;
    return TRUE;
}

bool SonixCam_UnInit()
{
	if (!camera_init)
		return FALSE;

	LibUsb_CloseDevice();

    camera_init = FALSE;
    return TRUE;
}

bool SonixCam_RestartDevice()
{
	if (!camera_init)
		return FALSE;

	return LibUsb_RestartDevice();
}


bool SonixCam_GetAsicRomType(DSP_ROM_TYPE *romType)
{
	if (!camera_init)
		return FALSE;

	BYTE chipID; 
	DSP_ARCH_TYPE dspArchType;
	*romType = LibUsb_GetChipRomType(&chipID, &dspArchType);
	return TRUE;
}

ERROR_CODE SonixCam_GetErrorCode()
{
	if (!camera_init)
		return EC_UnKnow;

	return gEC;
}

bool SonixCam_AsicRegisterRead(unsigned short addr, unsigned char pData[], long len)
{
	if (!camera_init)
		return FALSE;
	
	BYTE data = 0;
	USHORT startAddr = addr;
	LONG i = 0;
	for (i = 0; i < len; i++)
	{
		if (TRUE != LibUsb_ReadFromASIC((USHORT)startAddr++, &data))
			return FALSE;
		memcpy(pData + i, &data, 1);
	}
	return TRUE;
}

bool SonixCam_AsicRegisterWrite(unsigned short addr, unsigned char pData[], long len)
{
	if (!camera_init)
		return FALSE;
	
	BYTE data = 0;
	LONG startAddr = addr;
	LONG i = 0;
	for (i = 0; i < len; i++)
	{
		data = pData[i];
		if (TRUE != LibUsb_WriteToASIC((USHORT)startAddr++, data))
			return FALSE;
	}
	return TRUE;
}

bool SonixCam_SensorRegisterRead(unsigned char slaveId, unsigned short addr, unsigned char pData[], long len)
{
	if (!camera_init)
		return FALSE;

	LONG loop = len / 3;
	LONG ram = len % 3;
	BYTE tempData[3] = { 0 };
	LONG i = 0;
	for (i = 0; i < loop; i++)
	{
		if (TRUE != LibUsb_ReadFromSensor(slaveId, (USHORT)addr, tempData, 3))
			return FALSE;
        memcpy(&pData[i * 3], tempData, 3);
	}
	if (ram)
	{
		if (TRUE != LibUsb_ReadFromSensor(slaveId, (USHORT)addr, tempData, ram))
			return FALSE;
        memcpy(&pData[loop * 3], tempData, ram);
	}
	return TRUE;
}

bool SonixCam_SensorRegisterWrite(unsigned char slaveId, unsigned short addr, unsigned char pData[], long len)
{
	if (!camera_init)
		return FALSE;

	LONG loop = len / 3;
	LONG ram = len % 3;
	LONG i = 0;
	for (i = 0; i < loop; i++)
	{
		if (TRUE != LibUsb_WriteToSensor(slaveId, (USHORT)addr, &pData[i * 3], 3))
			return FALSE;
	}
	if (ram)
	{
		if (TRUE != LibUsb_WriteToSensor(slaveId, (USHORT)addr, &pData[loop * 3], ram))
			return FALSE;
	}
	return TRUE;
}

LONG GetByteLengthFormAddr(LONG addr)
{
	if (addr <= 0xFF)
		return 1;
	else if (addr <= 0xFFFF)
		return 2;
	else if (addr <= 0xFFFFFF)
		return 3;
	else
		return 4;
}

bool  SonixCam_SensorRegisterCustomRead(unsigned char slaveId, unsigned short  addr, unsigned short  addrByteNumber, unsigned char pData[], long dataByteNumber, bool pollSCL)
{
	if (!camera_init)
		return FALSE;

	USHORT temp = 0;
	if (!LibUsb_CustomReadFromSensor(slaveId, addr, addrByteNumber, &temp, dataByteNumber, pollSCL))
		return FALSE;
	if(dataByteNumber > 1){
		pData[0] = (BYTE)(temp >> 8);
		pData[1] = (BYTE)temp;
	}else{
		pData[0] = (BYTE)temp;
	}

	return TRUE;
}

bool  SonixCam_SensorRegisterCustomWrite(unsigned char slaveId, unsigned short addr, unsigned short  addrByteNumber, unsigned char pData[], long dataByteNumber, bool pollSCL)
{
	if (!camera_init)
		return FALSE;

	USHORT temp = 0;
	if(dataByteNumber > 1){
		temp = (USHORT)((USHORT)pData[0] << 8) + pData[1];
	}else{
		temp = pData[0];
	}
	if (!LibUsb_CustomWriteToSensor(slaveId, addr, addrByteNumber, temp, dataByteNumber, pollSCL))
		return false;

	return TRUE;
}

bool SonixCam_GetSerialFlashType(SERIAL_FLASH_TYPE *sft, bool check)
{
	if (!camera_init)
		return FALSE;

	return LibUsb_GetSerialFlashType(sft, check);
}

bool  SonixCam_SerialFlashRead(long addr, unsigned char pData[], long len)
{
	if (!camera_init)
		return FALSE;
	
	return LibUsb_ReadFormSF(addr, pData, len);
}

bool SonixCam_SerialFlashWrite(long addr, unsigned char pData[], long len)
{
	if (!camera_init)
		return FALSE;

	LONG startAddr = addr;
	LONG loop = len / 8;
	LONG ram = len % 8;
	BYTE tempData[8];
	LONG i = 0;
	for (i = 0; i < loop; i++)
	{
		memcpy(tempData, pData + i * 8, 8);
		if (!LibUsb_WriteDataToFlash(startAddr, tempData, 8))
			return FALSE;
		startAddr += 8;
	}

	if (ram > 0)
	{
		memset(&tempData, 0xFF, 8);
		memcpy(tempData, pData + (loop * 8), ram);
		if (!LibUsb_WriteDataToFlash(startAddr, tempData, ram)){
			return FALSE;
		}
	}

	return TRUE;
}

bool  SonixCam_SerialFlashSectorWrite(long addr, unsigned char pData[], long len, SERIAL_FLASH_TYPE sft)
{
	if (!camera_init)
		return FALSE;
	
	return LibUsb_WriteToSF(addr, pData, len, sft);
}


bool  SonixCam_GetFwVersion(unsigned char pData[], long len, BOOL bNormalExport)
{
	if (!camera_init)
		return FALSE;

	BYTE RomValue[10] = { 0 };
	BOOL hr = LibUsb_GetAsicRomVersion(RomValue);

	BYTE chipID;
	DSP_ARCH_TYPE dspArchType;
	if (DRT_Unknow == LibUsb_GetChipRomType(&chipID, &dspArchType))
		return FALSE;

	BYTE FlashCodeVer[56] = { 0 };
	BYTE CusVer[31];
	BYTE DayVer[31];
	BYTE Customer[31];

	switch (chipID){
	case 0x15:
		LibUsb_ReadFormSF(0x3E00, Customer + 2, 10);
		LibUsb_ReadFormSF(0x3E00 + 10, CusVer + 2, 10);
		LibUsb_ReadFormSF(0x3E00 + 20, DayVer + 2, 10);
		LibUsb_ReadFormSF(0x01e8 + 11, FlashCodeVer, 5);
		break;
	case 0x16:
		LibUsb_ReadFormSF(0x0FD0, Customer + 2, 10);
		LibUsb_ReadFormSF(0x0FD0 + 10, CusVer + 2, 10);
		LibUsb_ReadFormSF(0x0FD0 + 20, DayVer + 2, 10);
		LibUsb_ReadFormSF(0x0148 + 11, FlashCodeVer, 5);
		break;
	case 0x20:
		LibUsb_ReadFormSF(0x5E00, Customer + 2, 10);
		LibUsb_ReadFormSF(0x5E00 + 10, CusVer + 2, 10);
		LibUsb_ReadFormSF(0x5E00 + 20, DayVer + 2, 10);
		LibUsb_ReadFormSF(0x0 + 11, FlashCodeVer, 4);
		break;
	case 0x25:
		LibUsb_ReadFormSF(0x5E00, Customer + 2, 10);
		LibUsb_ReadFormSF(0x5E00 + 10, CusVer + 2, 10);
		LibUsb_ReadFormSF(0x5E00 + 20, DayVer + 2, 10);
		LibUsb_ReadFormSF(0x01e8 + 11, FlashCodeVer, 5);
		break;
	case 0x30:
		LibUsb_ReadFormSF(0x1E00, Customer + 2, 10);
		LibUsb_ReadFormSF(0x1E00 + 10, CusVer + 2, 10);
		LibUsb_ReadFormSF(0x1E00 + 20, DayVer + 2, 10);
		LibUsb_ReadFormSF(0x01e8 + 11, FlashCodeVer, 5);
	case 0x31:
		if (!hr){
			return FALSE;
		}
		if (RomValue[5] == 1){
			LibUsb_ReadFormSF(0x1E00, Customer + 2, 10);
			LibUsb_ReadFormSF(0x1E00 + 10, CusVer + 2, 10);
			LibUsb_ReadFormSF(0x1E00 + 20, DayVer + 2, 10);
			LibUsb_ReadFormSF(0x01e8 + 11, FlashCodeVer, 5);
		}
		else if (RomValue[5] == 2){
			LibUsb_ReadFormSF(0x6000 + 0x1E00, Customer + 2, 10);
			LibUsb_ReadFormSF(0x6000 + 0x1E00 + 10, CusVer + 2, 10);
			LibUsb_ReadFormSF(0x6000 + 0x1E00 + 20, DayVer + 2, 10);
			LibUsb_ReadFormSF(0x6000 + 0x01e8 + 11, FlashCodeVer, 5);
		}
		else{
			return FALSE;
		}

		break;
	case 0x32:
		if (!hr){
			return FALSE;
		}
		if (RomValue[5] == 1){
			LibUsb_ReadFormSF(0x0FD0, Customer + 2, 10);
			LibUsb_ReadFormSF(0x0FD0 + 10, CusVer + 2, 10);
			LibUsb_ReadFormSF(0x0FD0 + 20, DayVer + 2, 10);
			LibUsb_ReadFormSF(0x0148 + 11, FlashCodeVer, 5);
		}
		else if (RomValue[5] == 2){
			LibUsb_ReadFormSF(0x0FD0, Customer + 2, 10);
			LibUsb_ReadFormSF(0x0FD0 + 18, CusVer + 2, 10);
			LibUsb_ReadFormSF(0x0FD0 + 28, DayVer + 2, 10);
			LibUsb_ReadFormSF(0x0FD0 + 10, FlashCodeVer, 5);
		}
		else{
			return FALSE;
		}
		break;
	case 0x36:
		LibUsb_ReadFormSF(0x3E00, Customer + 2, 10);
		LibUsb_ReadFormSF(0x3E00 + 10, CusVer + 2, 10);
		LibUsb_ReadFormSF(0x3E00 + 20, DayVer + 2, 10);
		LibUsb_ReadFormSF(0x01e8 + 11, FlashCodeVer, 5);
		break;
	case 0x50:
		LibUsb_ReadFormSF(0x5E00, Customer + 2, 10);
		LibUsb_ReadFormSF(0x5E00 + 10, CusVer + 2, 10);
		LibUsb_ReadFormSF(0x5E00 + 20, DayVer + 2, 10);
		LibUsb_ReadFormSF(0x01e8 + 11, FlashCodeVer, 5);
		break;
	case 0x56:
		LibUsb_ReadFormSF(0x3E00, Customer + 2, 10);
		LibUsb_ReadFormSF(0x3E00 + 10, CusVer + 2, 10);
		LibUsb_ReadFormSF(0x3E00 + 20, DayVer + 2, 10);
		LibUsb_ReadFormSF(0x01e8 + 11, FlashCodeVer, 5);
		break;
	case 0x70:
		LibUsb_ReadFormSF(0x3E05, Customer + 2, 10);
		LibUsb_ReadFormSF(0x3E0F, CusVer + 2, 10);
		LibUsb_ReadFormSF(0x3E19, DayVer + 2, 10);
		LibUsb_ReadFormSF(0x3E00, FlashCodeVer, 5);
		break;
	case 0x71:
		LibUsb_ReadFormSF(0x3E05, Customer + 2, 10);
		LibUsb_ReadFormSF(0x3E0F, CusVer + 2, 10);
		LibUsb_ReadFormSF(0x3E19, DayVer + 2, 10);
		LibUsb_ReadFormSF(0x3E00, FlashCodeVer, 5);
		break;
	case 0x75:
		if (RomValue[5] == 1){
			LibUsb_ReadFormSF(0x2000, Customer + 2, 10);
			LibUsb_ReadFormSF(0x2012, CusVer + 2, 10);
			LibUsb_ReadFormSF(0x201C, DayVer + 2, 10);
			LibUsb_ReadFormSF(0x200A, FlashCodeVer, 5);
		}
		else{
			return FALSE;
		}

		break;
	case 0x76: //128K
		if (RomValue[5] == 1){
			LibUsb_ReadFormSF(0x3FD0, Customer + 2, 10);
			LibUsb_ReadFormSF(0x3FD0 + 10, CusVer + 2, 10);
			LibUsb_ReadFormSF(0x3FD0 + 20, DayVer + 2, 10);
			LibUsb_ReadFormSF(0x0148 + 11, FlashCodeVer, 5);
		}
		else{
			return FALSE;
		}
		break;
	case 0x83: //128K
		LibUsb_ReadFormSF(0x2000, Customer + 2, 10);
		LibUsb_ReadFormSF(0x2012, CusVer + 2, 10);
		LibUsb_ReadFormSF(0x201C, DayVer + 2, 10);
		LibUsb_ReadFormSF(0x200A, FlashCodeVer, 5);
	case 0x85: //128K
		LibUsb_ReadFormSF(0x2000, Customer + 2, 10);
		LibUsb_ReadFormSF(0x2012, CusVer + 2, 10);
		LibUsb_ReadFormSF(0x201C, DayVer + 2, 10);
		LibUsb_ReadFormSF(0x200A, FlashCodeVer, 5);
		break;
	case 0x86: //258K
		LibUsb_ReadFormSF(0x2000, Customer + 2, 10);
		LibUsb_ReadFormSF(0x2012, CusVer + 2, 10);
		LibUsb_ReadFormSF(0x201C, DayVer + 2, 10);
		LibUsb_ReadFormSF(0x200A, FlashCodeVer, 5);
		break;
	case 0x90:
		LibUsb_ReadFormSF(0x2000, Customer + 2, 10);
		LibUsb_ReadFormSF(0x2012, CusVer + 2, 10);
		LibUsb_ReadFormSF(0x201C, DayVer + 2, 10);
		LibUsb_ReadFormSF(0x200A, FlashCodeVer, 5);
		break;
	case 0x92: //128K
		LibUsb_ReadFormSF(0x2000, Customer + 2, 10);
		LibUsb_ReadFormSF(0x2012, CusVer + 2, 10);
		LibUsb_ReadFormSF(0x201C, DayVer + 2, 10);
		LibUsb_ReadFormSF(0x200A, FlashCodeVer, 5);
		break;
	default:
		return FALSE;
		break;
	}

	//220
	if (chipID == 0x20){
		FlashCodeVer[40] = '\0';
	}
	else{
		FlashCodeVer[41] = '\0';
	}

	if(bNormalExport){
		memcpy(FlashCodeVer + 5, CusVer + 2, 10);
		memcpy(FlashCodeVer + 15, Customer + 2, 10);
		memcpy(FlashCodeVer + 25, DayVer + 2, 10);
	}else{
		/* 第二种组合方式	*/
		BYTE cFLashCodeVer2 = FlashCodeVer[4];
		FlashCodeVer[4] = '-';
		int index = 0;
		BYTE *pFWVersion = FlashCodeVer;
		pFWVersion += 5;
		int i = 0;
		for (i = 0; i<10; i++)
		{
			if (CusVer[i + 2] != 0x2d)
			{
				*(pFWVersion++) = CusVer[i + 2];
			}
		}
		if ( 0 != memcmp(RomValue, "220R", 4))
		{
			*(pFWVersion++) = '-';
			*(pFWVersion++) = cFLashCodeVer2;
		}
		char cDayVer1[7] = {0};
		char cDayVer2[3] = {0};
		char cDayVer3[3] = {0};
		memcpy(cDayVer1, DayVer + 2, 6);
		memcpy(cDayVer2, DayVer + 8, 2);
		memcpy(cDayVer3, DayVer + 10, 2);

		*(pFWVersion++) = '-';
		*(pFWVersion++) = 'V';
		memcpy(pFWVersion, cDayVer1, 6);
		pFWVersion += 6;
		*(pFWVersion++) = '_';
		memcpy(pFWVersion, cDayVer2, 2);
		pFWVersion += 2;
		*(pFWVersion++) = '_';
		memcpy(pFWVersion, cDayVer3, 2);
		pFWVersion += 2;
		*(pFWVersion++) = '-';

		for (i = 0; i < 10; i++)
		{
			if (Customer[i + 2] != 0x2d)
			{
				*(pFWVersion++) = Customer[i + 2];
			}
		}
	}
	
	char Temp[56] = { 0 };
	memcpy(Temp, FlashCodeVer, 56);
	memcpy(pData, Temp, sizeof(Temp));
	return TRUE;
}

bool  SonixCam_GetFwVersionEx(DSP_ROM_TYPE romType, unsigned char pData[], long len, BOOL bNormalExport)
{
	if (!camera_init)
		return FALSE;

	BYTE RomValue[10] = { 0 };
	BOOL hr = LibUsb_GetAsicRomVersion(RomValue);

	BYTE chipID;
	DSP_ARCH_TYPE dspArchType;
	if (DRT_Unknow == LibUsb_GetChipRomType(&chipID, &dspArchType))
		return FALSE;

	BYTE FlashCodeVer[56] = { 0 };
	BYTE CusVer[31];
	BYTE DayVer[31];
	BYTE Customer[31];

	switch (chipID){
	case 0x15:
		LibUsb_ReadFormSF(0x3E00, Customer + 2, 10);
		LibUsb_ReadFormSF(0x3E00 + 10, CusVer + 2, 10);
		LibUsb_ReadFormSF(0x3E00 + 20, DayVer + 2, 10);
		LibUsb_ReadFormSF(0x01e8 + 11, FlashCodeVer, 5);
		break;
	case 0x16:
		LibUsb_ReadFormSF(0x0FD0, Customer + 2, 10);
		LibUsb_ReadFormSF(0x0FD0 + 10, CusVer + 2, 10);
		LibUsb_ReadFormSF(0x0FD0 + 20, DayVer + 2, 10);
		LibUsb_ReadFormSF(0x0148 + 11, FlashCodeVer, 5);
		break;
	case 0x20:
		LibUsb_ReadFormSF(0x5E00, Customer + 2, 10);
		LibUsb_ReadFormSF(0x5E00 + 10, CusVer + 2, 10);
		LibUsb_ReadFormSF(0x5E00 + 20, DayVer + 2, 10);
		LibUsb_ReadFormSF(0x0 + 11, FlashCodeVer, 4);
		break;
	case 0x25:
		LibUsb_ReadFormSF(0x5E00, Customer + 2, 10);
		LibUsb_ReadFormSF(0x5E00 + 10, CusVer + 2, 10);
		LibUsb_ReadFormSF(0x5E00 + 20, DayVer + 2, 10);
		LibUsb_ReadFormSF(0x01e8 + 11, FlashCodeVer, 5);
		break;
	case 0x30:
		LibUsb_ReadFormSF(0x1E00, Customer + 2, 10);
		LibUsb_ReadFormSF(0x1E00 + 10, CusVer + 2, 10);
		LibUsb_ReadFormSF(0x1E00 + 20, DayVer + 2, 10);
		LibUsb_ReadFormSF(0x01e8 + 11, FlashCodeVer, 5);
	case 0x31:
		if (!hr){
			return FALSE;
		}
		if (RomValue[5] == 1){
			LibUsb_ReadFormSF(0x1E00, Customer + 2, 10);
			LibUsb_ReadFormSF(0x1E00 + 10, CusVer + 2, 10);
			LibUsb_ReadFormSF(0x1E00 + 20, DayVer + 2, 10);
			LibUsb_ReadFormSF(0x01e8 + 11, FlashCodeVer, 5);
		}
		else if (RomValue[5] == 2){
			LibUsb_ReadFormSF(0x6000 + 0x1E00, Customer + 2, 10);
			LibUsb_ReadFormSF(0x6000 + 0x1E00 + 10, CusVer + 2, 10);
			LibUsb_ReadFormSF(0x6000 + 0x1E00 + 20, DayVer + 2, 10);
			LibUsb_ReadFormSF(0x6000 + 0x01e8 + 11, FlashCodeVer, 5);
		}
		else{
			return FALSE;
		}

		break;
	case 0x32:
		if (!hr){
			return FALSE;
		}
		if (RomValue[5] == 1){
			LibUsb_ReadFormSF(0x0FD0, Customer + 2, 10);
			LibUsb_ReadFormSF(0x0FD0 + 10, CusVer + 2, 10);
			LibUsb_ReadFormSF(0x0FD0 + 20, DayVer + 2, 10);
			LibUsb_ReadFormSF(0x0148 + 11, FlashCodeVer, 5);
		}
		else if (RomValue[5] == 2){
			LibUsb_ReadFormSF(0x0FD0, Customer + 2, 10);
			LibUsb_ReadFormSF(0x0FD0 + 18, CusVer + 2, 10);
			LibUsb_ReadFormSF(0x0FD0 + 28, DayVer + 2, 10);
			LibUsb_ReadFormSF(0x0FD0 + 10, FlashCodeVer, 5);
		}
		else{
			return FALSE;
		}
		break;
	case 0x36:
		LibUsb_ReadFormSF(0x3E00, Customer + 2, 10);
		LibUsb_ReadFormSF(0x3E00 + 10, CusVer + 2, 10);
		LibUsb_ReadFormSF(0x3E00 + 20, DayVer + 2, 10);
		LibUsb_ReadFormSF(0x01e8 + 11, FlashCodeVer, 5);
		break;
	case 0x50:
		LibUsb_ReadFormSF(0x5E00, Customer + 2, 10);
		LibUsb_ReadFormSF(0x5E00 + 10, CusVer + 2, 10);
		LibUsb_ReadFormSF(0x5E00 + 20, DayVer + 2, 10);
		LibUsb_ReadFormSF(0x01e8 + 11, FlashCodeVer, 5);
		break;
	case 0x56:
		LibUsb_ReadFormSF(0x3E00, Customer + 2, 10);
		LibUsb_ReadFormSF(0x3E00 + 10, CusVer + 2, 10);
		LibUsb_ReadFormSF(0x3E00 + 20, DayVer + 2, 10);
		LibUsb_ReadFormSF(0x01e8 + 11, FlashCodeVer, 5);
		break;
	case 0x70:
		LibUsb_ReadFormSF(0x3E05, Customer + 2, 10);
		LibUsb_ReadFormSF(0x3E0F, CusVer + 2, 10);
		LibUsb_ReadFormSF(0x3E19, DayVer + 2, 10);
		LibUsb_ReadFormSF(0x3E00, FlashCodeVer, 5);
		break;
	case 0x71:
		LibUsb_ReadFormSF(0x3E05, Customer + 2, 10);
		LibUsb_ReadFormSF(0x3E0F, CusVer + 2, 10);
		LibUsb_ReadFormSF(0x3E19, DayVer + 2, 10);
		LibUsb_ReadFormSF(0x3E00, FlashCodeVer, 5);
		break;
	case 0x75:
		if (RomValue[5] == 1){
			
			if(romType == DRT_64K){
				LibUsb_ReadFormSF(0x4E00, Customer + 2, 10);
				LibUsb_ReadFormSF(0x4E12, CusVer + 2, 10);
				LibUsb_ReadFormSF(0x4E1C, DayVer + 2, 10);
				LibUsb_ReadFormSF(0x4E0A, FlashCodeVer, 5);
				printf("dsp rom type=%s\n", Customer);
			}
			else if(romType == DRT_128K){
				LibUsb_ReadFormSF(0x2000, Customer + 2, 10);
				LibUsb_ReadFormSF(0x2012, CusVer + 2, 10);
				LibUsb_ReadFormSF(0x201C, DayVer + 2, 10);
				LibUsb_ReadFormSF(0x200A, FlashCodeVer, 5);
			}
			else
			{
				return FALSE;
			}
		}
		else{
			return FALSE;
		}

		break;
	case 0x76: //128K
		if (RomValue[5] == 1){
			LibUsb_ReadFormSF(0x3FD0, Customer + 2, 10);
			LibUsb_ReadFormSF(0x3FD0 + 10, CusVer + 2, 10);
			LibUsb_ReadFormSF(0x3FD0 + 20, DayVer + 2, 10);
			LibUsb_ReadFormSF(0x0148 + 11, FlashCodeVer, 5);
		}
		else{
			return FALSE;
		}
		break;
	case 0x83: //128K
		LibUsb_ReadFormSF(0x2000, Customer + 2, 10);
		LibUsb_ReadFormSF(0x2012, CusVer + 2, 10);
		LibUsb_ReadFormSF(0x201C, DayVer + 2, 10);
		LibUsb_ReadFormSF(0x200A, FlashCodeVer, 5);
	case 0x85: //128K
		LibUsb_ReadFormSF(0x2000, Customer + 2, 10);
		LibUsb_ReadFormSF(0x2012, CusVer + 2, 10);
		LibUsb_ReadFormSF(0x201C, DayVer + 2, 10);
		LibUsb_ReadFormSF(0x200A, FlashCodeVer, 5);
		break;
	case 0x86: //258K
		LibUsb_ReadFormSF(0x2000, Customer + 2, 10);
		LibUsb_ReadFormSF(0x2012, CusVer + 2, 10);
		LibUsb_ReadFormSF(0x201C, DayVer + 2, 10);
		LibUsb_ReadFormSF(0x200A, FlashCodeVer, 5);
		break;		
	case 0x90:
		LibUsb_ReadFormSF(0x2000, Customer + 2, 10);
		LibUsb_ReadFormSF(0x2012, CusVer + 2, 10);
		LibUsb_ReadFormSF(0x201C, DayVer + 2, 10);
		LibUsb_ReadFormSF(0x200A, FlashCodeVer, 5);
		break;
	case 0x92: //128K
		LibUsb_ReadFormSF(0x2000, Customer + 2, 10);
		LibUsb_ReadFormSF(0x2012, CusVer + 2, 10);
		LibUsb_ReadFormSF(0x201C, DayVer + 2, 10);
		LibUsb_ReadFormSF(0x200A, FlashCodeVer, 5);
		break;
	default:
		return FALSE;
		break;
	}

	//220
	if (chipID == 0x20){
		FlashCodeVer[40] = '\0';
	}
	else{
		FlashCodeVer[41] = '\0';
	}


	if(bNormalExport){
		memcpy(FlashCodeVer + 5, CusVer + 2, 10);
		memcpy(FlashCodeVer + 15, Customer + 2, 10);
		memcpy(FlashCodeVer + 25, DayVer + 2, 10);
	}else{
		/* 第二种组合方式	*/
		BYTE cFLashCodeVer2 = FlashCodeVer[4];
		FlashCodeVer[4] = '-';
		int index = 0;
		BYTE *pFWVersion = FlashCodeVer;
		pFWVersion += 5;
		int i = 0;
		for (i = 0; i<10; i++)
		{
			if (CusVer[i + 2] != 0x2d)
			{
				*(pFWVersion++) = CusVer[i + 2];
			}
		}
		if ( 0 != memcmp(RomValue, "220R", 4))
		{
			*(pFWVersion++) = '-';
			*(pFWVersion++) = cFLashCodeVer2;
		}
		char cDayVer1[7] = {0};
		char cDayVer2[3] = {0};
		char cDayVer3[3] = {0};
		memcpy(cDayVer1, DayVer + 2, 6);
		memcpy(cDayVer2, DayVer + 8, 2);
		memcpy(cDayVer3, DayVer + 10, 2);

		*(pFWVersion++) = '-';
		*(pFWVersion++) = 'V';
		memcpy(pFWVersion, cDayVer1, 6);
		pFWVersion += 6;
		*(pFWVersion++) = '_';
		memcpy(pFWVersion, cDayVer2, 2);
		pFWVersion += 2;
		*(pFWVersion++) = '_';
		memcpy(pFWVersion, cDayVer3, 2);
		pFWVersion += 2;
		*(pFWVersion++) = '-';

		for (i = 0; i < 10; i++)
		{
			if (Customer[i + 2] != 0x2d)
			{
				*(pFWVersion++) = Customer[i + 2];
			}
		}
	}

	char Temp[56] = { 0 };
	memcpy(Temp, FlashCodeVer, 56);
	memcpy(pData, Temp, sizeof(Temp));
	return TRUE;
}

bool  SonixCam_GetFwVersionFromFile(unsigned char pFwFile[], unsigned char pData[], long len, bool bNormalExport)
{
	if (!camera_init)
		return FALSE;

	BYTE RomValue[10] = { 0 };
	BOOL hr = LibUsb_GetAsicRomVersion(RomValue);

	BYTE chipID;
	DSP_ARCH_TYPE dspArchType;
	if (DRT_Unknow == LibUsb_GetChipRomType(&chipID, &dspArchType))
		return FALSE;

	BYTE FlashCodeVer[56] = { 0 };
	BYTE CusVer[31];
	BYTE DayVer[31];
	BYTE Customer[31];

	switch (chipID){
	case 0x15:
		memcpy(Customer + 2, pFwFile + 0x3E00, 10);
		memcpy(CusVer + 2, pFwFile + 0x3E00 + 10, 10);
		memcpy(DayVer + 2, pFwFile + 0x3E00 + 20, 10);
		memcpy(FlashCodeVer, pFwFile + 0x01e8 + 11, 5);
		break;
	case 0x16:
		memcpy(Customer + 2, pFwFile + 0x0FD0, 10);
		memcpy(CusVer + 2, pFwFile + 0x0FD0 + 10, 10);
		memcpy(DayVer + 2, pFwFile + 0x0FD0 + 20, 10);
		memcpy(FlashCodeVer, pFwFile + 0x0148 + 11, 5);
		break;
	case 0x20:
		memcpy(Customer + 2, pFwFile + 0x5E00, 10);
		memcpy(CusVer + 2, pFwFile + 0x5E00 + 10, 10);
		memcpy(DayVer + 2, pFwFile + 0x5E00 + 20, 10);
		memcpy(FlashCodeVer, pFwFile + 0x0 + 11, 4);
		break;
	case 0x25:
		memcpy(Customer + 2, pFwFile + 0x5E00, 10);
		memcpy(CusVer + 2, pFwFile + 0x5E00 + 10, 10);
		memcpy(DayVer + 2, pFwFile + 0x5E00 + 20, 10);
		memcpy(FlashCodeVer, pFwFile + 0x01e8 + 11, 5);
		break;
	case 0x30:
		memcpy(Customer + 2, pFwFile + 0x1E00, 10);
		memcpy(CusVer + 2, pFwFile + 0x1E00 + 10, 10);
		memcpy(DayVer + 2, pFwFile + 0x1E00 + 20, 10);
		memcpy(FlashCodeVer, pFwFile + 0x01e8 + 11, 5);
	case 0x31:
		if (!hr){
			return false;
		}
		if (RomValue[5] == 1){
			memcpy(Customer + 2, pFwFile + 0x1E00, 10);
			memcpy(CusVer + 2, pFwFile + 0x1E00 + 10, 10);
			memcpy(DayVer + 2, pFwFile + 0x1E00 + 20, 10);
			memcpy(FlashCodeVer, pFwFile + 0x01e8 + 11, 5);
		}
		else if (RomValue[5] == 2){
			memcpy(Customer + 2, pFwFile + 0x6000 + 0x1E00, 10);
			memcpy(CusVer + 2, pFwFile + 0x6000 + 0x1E00 + 10, 10);
			memcpy(DayVer + 2, pFwFile + +0x1E00 + 0x1E00 + 20, 10);
			memcpy(FlashCodeVer, pFwFile + 0x6000 + 0x01e8 + 11, 5);
		}
		else{
			return false;
		}

		break;
	case 0x32:
		if (!hr){
			return false;
		}
		if (RomValue[5] == 1){
			memcpy(Customer + 2, pFwFile + 0x0FD0, 10);
			memcpy(CusVer + 2, pFwFile + 0x0FD0 + 10, 10);
			memcpy(DayVer + 2, pFwFile + 0x0FD0 + 20, 10);
			memcpy(FlashCodeVer, pFwFile + 0x0148 + 11, 5);
		}
		else if (RomValue[5] == 2){
			memcpy(Customer + 2, pFwFile + 0x0FD0, 10);
			memcpy(CusVer + 2, pFwFile + 0x0FD0 + 18, 10);
			memcpy(DayVer + 2, pFwFile + 0x0FD0 + 28, 10);
			memcpy(FlashCodeVer, pFwFile + 0x0FD0 + 10, 5);
		}
		else{
			return false;
		}
		break;
	case 0x36:
		memcpy(Customer + 2, pFwFile + 0x3E00, 10);
		memcpy(CusVer + 2, pFwFile + 0x3E00 + 10, 10);
		memcpy(DayVer + 2, pFwFile + 0x3E00 + 20, 10);
		memcpy(FlashCodeVer, pFwFile + 0x01e8 + 11, 5);
		break;
	case 0x50:
		memcpy(Customer + 2, pFwFile + 0x5E00, 10);
		memcpy(CusVer + 2, pFwFile + 0x5E00 + 10, 10);
		memcpy(DayVer + 2, pFwFile + 0x5E00 + 20, 10);
		memcpy(FlashCodeVer, pFwFile + 0x01e8 + 11, 5);
		break;
	case 0x56:
		memcpy(Customer + 2, pFwFile + 0x3E00, 10);
		memcpy(CusVer + 2, pFwFile + 0x3E00 + 10, 10);
		memcpy(DayVer + 2, pFwFile + 0x3E00 + 20, 10);
		memcpy(FlashCodeVer, pFwFile + 0x01e8 + 11, 5);
		break;
	case 0x70:
		memcpy(Customer + 2, pFwFile + 0x3E05, 10);
		memcpy(CusVer + 2, pFwFile + 0x3E0F, 10);
		memcpy(DayVer + 2, pFwFile + 0x3E19, 10);
		memcpy(FlashCodeVer, pFwFile + 0x3E00, 5);
		break;
	case 0x71:
		memcpy(Customer + 2, pFwFile + 0x3E05, 10);
		memcpy(CusVer + 2, pFwFile + 0x3E0F, 10);
		memcpy(DayVer + 2, pFwFile + 0x3E19, 10);
		memcpy(FlashCodeVer, pFwFile + 0x3E00, 5);
		break;
	case 0x75:
		if (RomValue[5] == 1){
			memcpy(Customer + 2, pFwFile + 0x2000, 10);
			memcpy(CusVer + 2, pFwFile + 0x2012, 10);
			memcpy(DayVer + 2, pFwFile + 0x201C, 10);
			memcpy(FlashCodeVer, pFwFile + 0x200A, 5);
		}
		else{
			return false;
		}

		break;
	case 0x76: //128K
		if (RomValue[5] == 1){
			memcpy(Customer + 2, pFwFile + 0x3FD0, 10);
			memcpy(CusVer + 2, pFwFile + 0x3FD0 + 10, 10);
			memcpy(DayVer + 2, pFwFile + 0x3FD0 + 20, 10);
			memcpy(FlashCodeVer, pFwFile + 0x0148 + 11, 5);
		}
		else{
			return false;
		}
		break;
	case 0x83: //128K
		memcpy(Customer + 2, pFwFile + 0x2000, 10);
		memcpy(CusVer + 2, pFwFile + 0x2012, 10);
		memcpy(DayVer + 2, pFwFile + 0x201C, 10);
		memcpy(FlashCodeVer, pFwFile + 0x200A, 5);
		break;
	case 0x85: //128K
		memcpy(Customer + 2, pFwFile + 0x2000, 10);
		memcpy(CusVer + 2, pFwFile + 0x2012, 10);
		memcpy(DayVer + 2, pFwFile + 0x201C, 10);
		memcpy(FlashCodeVer, pFwFile + 0x200A, 5);
		break;
	case 0x86: //128K
		memcpy(Customer + 2, pFwFile + 0x2000, 10);
		memcpy(CusVer + 2, pFwFile + 0x2012, 10);
		memcpy(DayVer + 2, pFwFile + 0x201C, 10);
		memcpy(FlashCodeVer, pFwFile + 0x200A, 5);
		break;
	case 0x90:
		memcpy(Customer + 2, pFwFile + 0x2000, 10);
		memcpy(CusVer + 2, pFwFile + 0x2012, 10);
		memcpy(DayVer + 2, pFwFile + 0x201C, 10);
		memcpy(FlashCodeVer, pFwFile + 0x200A, 5);
		break;
	case 0x92: //128K
		memcpy(Customer + 2, pFwFile + 0x2000, 10);
		memcpy(CusVer + 2, pFwFile + 0x2012, 10);
		memcpy(DayVer + 2, pFwFile + 0x201C, 10);
		memcpy(FlashCodeVer, pFwFile + 0x200A, 5);
		break;
	default:
		return false;
		break;
	}

	//220
	if (chipID == 0x20){
		FlashCodeVer[40] = '\0';
	}
	else{
		FlashCodeVer[41] = '\0';
	}

	if(bNormalExport){
		memcpy(FlashCodeVer + 5, CusVer + 2, 10);
		memcpy(FlashCodeVer + 15, Customer + 2, 10);
		memcpy(FlashCodeVer + 25, DayVer + 2, 10);
	}else{
		/* 第二种组合方式	*/
		BYTE cFLashCodeVer2 = FlashCodeVer[4];
		FlashCodeVer[4] = '-';
		int index = 0;
		BYTE *pFWVersion = FlashCodeVer;
		pFWVersion += 5;
		int i = 0;
		for (i = 0; i<10; i++)
		{
			if (CusVer[i + 2] != 0x2d)
			{
				*(pFWVersion++) = CusVer[i + 2];
			}
		}
		if ( 0 != memcmp(RomValue, "220R", 4))
		{
			*(pFWVersion++) = '-';
			*(pFWVersion++) = cFLashCodeVer2;
		}
		char cDayVer1[7] = {0};
		char cDayVer2[3] = {0};
		char cDayVer3[3] = {0};
		memcpy(cDayVer1, DayVer + 2, 6);
		memcpy(cDayVer2, DayVer + 8, 2);
		memcpy(cDayVer3, DayVer + 10, 2);

		*(pFWVersion++) = '-';
		*(pFWVersion++) = 'V';
		memcpy(pFWVersion, cDayVer1, 6);
		pFWVersion += 6;
		*(pFWVersion++) = '_';
		memcpy(pFWVersion, cDayVer2, 2);
		pFWVersion += 2;
		*(pFWVersion++) = '_';
		memcpy(pFWVersion, cDayVer3, 2);
		pFWVersion += 2;
		*(pFWVersion++) = '-';

		for (i = 0; i < 10; i++)
		{
			if (Customer[i + 2] != 0x2d)
			{
				*(pFWVersion++) = Customer[i + 2];
			}
		}
	}
	
	char Temp[56] = { 0 };
	memcpy(Temp, FlashCodeVer, 56);
	memcpy(pData, Temp, sizeof(Temp));
	return TRUE;
}

bool SonixCam_GetSerialNumber(unsigned char pData[], long len)
{
	if (!camera_init)
		return FALSE;
	
	return LibUsb_GetStringSettingFormSF(pData, len, 0xC0, TRUE);
}

bool  SonixCam_GetManufacturer(unsigned char pData[], long len)
{
	if (!camera_init)
		return FALSE;

	return LibUsb_GetStringSettingFormSF(pData, len, 0x80, TRUE);
}

bool  SonixCam_GetProduct(unsigned char pData[], long len)
{
	if (!camera_init)
		return FALSE;

	return LibUsb_GetStringSettingFormSF(pData, len, 0x40, TRUE);
}

bool  SonixCam_GetVidPid(unsigned char pData[], long len)
{
	if (!camera_init)
		return FALSE;

	DWORD dwStringAddr = 0;
	ULONG dwParaTableStartAddr = 0;
	ULONG dwParaTableEndAddr = 0;
	ULONG dwCRCStartAddr = 0;
	if (!LibUsb_GetParaTableAndCRCAddrFormSF(&dwParaTableStartAddr, &dwParaTableEndAddr, &dwCRCStartAddr))
		return FALSE;

	dwStringAddr = dwParaTableStartAddr + 0x06;
	BYTE pbyStringBuf[4] = { 0 };
	if (!LibUsb_ReadFormSF(dwStringAddr, pbyStringBuf, sizeof(pbyStringBuf)))
		return FALSE;

	memcpy(pData, pbyStringBuf, 4);
	return TRUE;
}

bool SonixCam_GetString3(unsigned char pData[], long len)
{
	if (!camera_init)
		return FALSE;

	return LibUsb_GetStringSettingFormSF(pData, len, 0x100, TRUE);
}

bool SonixCam_GetInterface(unsigned char pData[], long len)
{
	if (!camera_init)
		return FALSE;

	return LibUsb_GetStringSettingFormSF(pData, len, 0x140, TRUE);
}

bool SonixCam_XuRead(unsigned char pData[], unsigned int length, unsigned char unitID, unsigned char cs)
{
	if (!camera_init)
		return FALSE;

	if(!XU_Read(pData, length, unitID, cs))
		return FALSE;
	return TRUE;
}

bool SonixCam_XuWrite(unsigned char pData[], unsigned int length, unsigned char unitID, unsigned char cs)
{

	if (!camera_init)
		return FALSE;

	if(!XU_Write(pData, length, unitID, cs))
		return FALSE;
	return TRUE;
}

bool SonixCam_DisableSerialFlashWriteProtect(SERIAL_FLASH_TYPE sft)
{
	if (!camera_init)
		return FALSE;
	
	if (!LibUsb_DisableSerialFlashWriteProtect(sft))
	{
		gEC = EC_DisableFlashWriteProtectFail;
		return FALSE;
	}
	return TRUE;
}

bool SonixCam_EraseBlockFlash(long addr, SERIAL_FLASH_TYPE sft)
{
	if (!camera_init)
		return FALSE;

	if (!LibUsb_DisableSerialFlashWriteProtect(sft))
	{
		gEC = EC_DisableFlashWriteProtectFail;
		return FALSE;
	}

	if (!LibUsb_EraseBlockForSerialFlash(addr, sft))
	{
		gEC = EC_EraseFlashFail;
		return FALSE;
	}
	return TRUE;
}

bool SonixCam_EraseSectorFlash(long addr, SERIAL_FLASH_TYPE sft)
{
	if (!camera_init)
		return FALSE;

	if (!LibUsb_DisableSerialFlashWriteProtect(sft))
	{
		gEC = EC_DisableFlashWriteProtectFail;
		return FALSE;
	}

	if (!LibUsb_EraseSectorForSerialFlash(addr, sft))
	{
		gEC = EC_EraseFlashFail;
		return FALSE;
	}
	return TRUE;
}

bool SonixCam_EraseSerialFlash(SERIAL_FLASH_TYPE sft)
{
	if (!camera_init)
		return FALSE;

	if (!LibUsb_DisableSerialFlashWriteProtect(sft))
	{
		gEC = EC_DisableFlashWriteProtectFail;
		return FALSE;
	}

	if (!LibUsb_SerialFlashErase(sft))
	{
		gEC = EC_EraseFlashFail;
		return FALSE;
	}
	return TRUE;
}

bool  SonixCam_SerialFlashCustomRead(long addr, unsigned char pData[], long len)
{
	if (!camera_init)
		return FALSE;

	LibUsb_EnableAsicRegisterBit(sfModeAddr, 0);//series flash mode
	LibUsb_DisableAsicRegisterBit(sfCSAddr, 0);//CS -> 0

	BYTE data = 3;
	LibUsb_WriteToASIC(0x1088, data);//read command 0x1088 = 0x03
	LibUsb_WriteToASIC(sfWriteDataAddr, data);
	LibUsb_EnableAsicRegisterBit(sfReadWriteTriggerAddr, 0);

	LONG startAddr = addr;
	data = startAddr >> 16;
	LibUsb_WriteToASIC(0x1089, data);
	LibUsb_WriteToASIC(sfWriteDataAddr, data);//addr0
	LibUsb_EnableAsicRegisterBit(sfReadWriteTriggerAddr, 0);
	LibUsb_SFWaitReady();

	data = startAddr >> 8;
	LibUsb_WriteToASIC(0x108a, data);
	LibUsb_WriteToASIC(sfWriteDataAddr, data);//addr1
	LibUsb_EnableAsicRegisterBit(sfReadWriteTriggerAddr, 0);
	LibUsb_SFWaitReady();

	data = (BYTE)startAddr;
	LibUsb_WriteToASIC(0x108b, data);
	LibUsb_WriteToASIC(sfWriteDataAddr, data);//addr2
	LibUsb_EnableAsicRegisterBit(sfReadWriteTriggerAddr, 0);
	LibUsb_SFWaitReady();

	LONG i = 0;
	for (i = 0; i < len; i++)
	{
		data = 0;
		LibUsb_WriteToASIC(sfReadDataAddr, data);//ready for read
		LibUsb_EnableAsicRegisterBit(sfReadWriteTriggerAddr, 1);	//read TRG
		LibUsb_SFWaitReady();//read 1084 bit0 when bit0 is 1 means ISP controler is ready
		//500us timeout
		LibUsb_ReadFromASIC(sfReadDataAddr, &pData[i]);//read data
	}
	LibUsb_EnableAsicRegisterBit(sfCSAddr, 0);//CS -> 1
	LibUsb_DisableAsicRegisterBit(sfModeAddr, 0);//series flash mode disable	
	return TRUE;
}

bool  SonixCam_SerialFlashSectorCustomWrite(long addr, unsigned char pData[], long len, SERIAL_FLASH_TYPE sft)
{
	if (!camera_init)
		return FALSE;

	// 0x1080 [1 : Serial Flash mode]
	// 0x1081 [1:SF_WRITE_TRG Trigger  2:SF_READ_TRG] 
	// 0x1082 [SF_WRITE_DATA[7:0]
	// 0x1083 [SF_READ_DATA[7:0]
	// 0x1091 [0: SF chip select] 

	//disable serial flash wirte protect
	if (!LibUsb_DisableSerialFlashWriteProtect(sft))
		return FALSE;

	//erase serial flash sector 
	if (!LibUsb_EraseSectorForSerialFlash(addr, sft))
		return FALSE;
	sleep(1);
	LibUsb_SFWaitReady();
	
	LibUsb_EnableAsicRegisterBit(sfModeAddr, 0);			// Flash Mode:En
	//WREN cycle
	LibUsb_DisableAsicRegisterBit(sfCSAddr, 0);			// CS:0
	BYTE data = 6;
	LibUsb_WriteToASIC(sfWriteDataAddr, data);					//WREN
	LibUsb_EnableAsicRegisterBit(sfReadWriteTriggerAddr, 0);
	LibUsb_SFWaitReady();
	LibUsb_EnableAsicRegisterBit(sfCSAddr, 0);			// CS:1

	LONG startAddr = addr;
	if (sft == SFT_SST)
	{
		LibUsb_DisableAsicRegisterBit(sfCSAddr, 0);
		data = 0xaf;
		LibUsb_WriteToASIC(sfWriteDataAddr, data);
		LibUsb_EnableAsicRegisterBit(sfReadWriteTriggerAddr, 0);
		LibUsb_SFWaitReady();

		data = startAddr >> 16;
		LibUsb_WriteToASIC(sfWriteDataAddr, data);
		LibUsb_EnableAsicRegisterBit(sfReadWriteTriggerAddr, 0);
		LibUsb_SFWaitReady();
		data = startAddr >> 8;
		LibUsb_WriteToASIC(sfWriteDataAddr, data);				//addr2
		LibUsb_EnableAsicRegisterBit(sfReadWriteTriggerAddr, 0);
		LibUsb_SFWaitReady();
		data = (BYTE)startAddr;
		LibUsb_WriteToASIC(sfWriteDataAddr, data);				//addr3
		LibUsb_EnableAsicRegisterBit(sfReadWriteTriggerAddr, 0);
		LibUsb_SFWaitReady();
		LONG i = 0;
		for (i = 0; i < len; i++)
		{
			LibUsb_WriteToASIC(sfWriteDataAddr, pData[i]);		//Data
			LibUsb_EnableAsicRegisterBit(sfReadWriteTriggerAddr, 0);
			LibUsb_SFWaitReady();
			LibUsb_EnableAsicRegisterBit(sfCSAddr, 0);				// CS:1
			if (i == len - 1)
				break;
			LibUsb_DisableAsicRegisterBit(sfCSAddr, 0);				// CS:0
			data = 0xaf;
			LibUsb_WriteToASIC(sfWriteDataAddr, data);				//PP  [0xaf:SST 0x2:other]
			LibUsb_EnableAsicRegisterBit(sfReadWriteTriggerAddr, 0);
			LibUsb_SFWaitReady();
		}
		//WRDI
		LibUsb_DisableAsicRegisterBit(sfCSAddr, 0);			// CS:0
		data = 4;
		LibUsb_WriteToASIC(sfWriteDataAddr, data);
		LibUsb_EnableAsicRegisterBit(sfReadWriteTriggerAddr, 0);
		LibUsb_SFWaitReady();
		LibUsb_EnableAsicRegisterBit(sfCSAddr, 0);			// CS:1
		usleep(100000);
		LibUsb_SFWaitReady();
	}
	else if (sft == SFT_MXIC || sft == SFT_GIGA)
	{
		LONG j = 0;
		do{
			//WREN cycle
			LibUsb_DisableAsicRegisterBit(sfCSAddr, 0);			// CS:0
			BYTE data = 6;
			LibUsb_WriteToASIC(sfWriteDataAddr, data);					//WREN
			LibUsb_EnableAsicRegisterBit(sfReadWriteTriggerAddr, 0);
			LibUsb_SFWaitReady();
			LibUsb_EnableAsicRegisterBit(sfCSAddr, 0);			// CS:1

			LibUsb_DisableAsicRegisterBit(sfCSAddr, 0);			// CS:0
			data = 2;									
			LibUsb_WriteToASIC(sfWriteDataAddr, data);
			LibUsb_EnableAsicRegisterBit(sfReadWriteTriggerAddr, 0);
			LibUsb_SFWaitReady();								//addr1
			data = startAddr >> 16;
			LibUsb_WriteToASIC(sfWriteDataAddr, data);
			LibUsb_EnableAsicRegisterBit(sfReadWriteTriggerAddr, 0);
			LibUsb_SFWaitReady();
			data = startAddr >> 8;
			LibUsb_WriteToASIC(sfWriteDataAddr, data);				//addr2
			LibUsb_EnableAsicRegisterBit(sfReadWriteTriggerAddr, 0);
			LibUsb_SFWaitReady();
			data = (BYTE)startAddr;
			LibUsb_WriteToASIC(sfWriteDataAddr, data);				//addr3
			LibUsb_EnableAsicRegisterBit(sfReadWriteTriggerAddr, 0);
			LibUsb_SFWaitReady();
			for (; j < len;)
			{
				LibUsb_WriteToASIC(sfWriteDataAddr, pData[j]);		//Data
				LibUsb_EnableAsicRegisterBit(sfReadWriteTriggerAddr, 0);
				LibUsb_SFWaitReady();
				startAddr++;
				j++;
				if (0 == startAddr % 256)
				{
					LibUsb_EnableAsicRegisterBit(sfCSAddr, 0);	// CS:1
					break;
				}
			}
			if (j == len)
			{
				LibUsb_EnableAsicRegisterBit(sfCSAddr, 0);	// CS:1
				break;
			}
		} while (1);
	}
	else
	{
		LibUsb_DisableAsicRegisterBit(sfCSAddr, 0);				// CS:0
		data = 2;									//PP  modify from ldata = 2;  // 0x2:other   0xaf:SST
		LibUsb_WriteToASIC(sfWriteDataAddr, data);
		LibUsb_EnableAsicRegisterBit(sfReadWriteTriggerAddr, 0);
		LibUsb_SFWaitReady();
		//ldata = 0;									//addr1
		data = startAddr >> 16;
		LibUsb_WriteToASIC(sfWriteDataAddr, data);
		LibUsb_EnableAsicRegisterBit(sfReadWriteTriggerAddr, 0);
		LibUsb_SFWaitReady();
		data = startAddr >> 8;
		LibUsb_WriteToASIC(sfWriteDataAddr, data);		//addr2
		LibUsb_EnableAsicRegisterBit(sfReadWriteTriggerAddr, 0);
		LibUsb_SFWaitReady();
		data = (BYTE)startAddr;
		LibUsb_WriteToASIC(sfWriteDataAddr, data);		//addr3
		LibUsb_EnableAsicRegisterBit(sfReadWriteTriggerAddr, 0);
		LibUsb_SFWaitReady();
		LONG i = 0;
		for (i = 0; i < len; i++)
		{
			LibUsb_WriteToASIC(sfWriteDataAddr, pData[i]);  //Data
			LibUsb_EnableAsicRegisterBit(sfReadWriteTriggerAddr, 0);
			LibUsb_SFWaitReady();
		}

		LibUsb_EnableAsicRegisterBit(sfCSAddr, 0);				// CS:1
	}
	LibUsb_DisableAsicRegisterBit(sfModeAddr, 0);				// Flash Mode:Dis
	return TRUE;
}

bool  SonixCam_BurnerFW(unsigned char pFwBuffer[], LONG lFwLength, SonixCam_SetProgress setProgress, void *ptrClass, SERIAL_FLASH_TYPE sft, BOOL bFullCheckFW)
{
	if (!camera_init)
		return FALSE;

	if (sft == SFT_UNKNOW)
	{	
		gEC = EC_UnKnowSerialFlashType;
		return FALSE;
	}
	
	BYTE chipID;
	DSP_ARCH_TYPE asicArchType;
	DSP_ROM_TYPE romType = LibUsb_GetChipRomType(&chipID, &asicArchType);
	if (romType == DRT_Unknow)
		return FALSE;
	switch (chipID)
	{
	case 0x85:
		LibUsb_WriteToASIC(0x5FF, 0x5A);
		LibUsb_WriteToASIC(0xA00, 0x1); // first frame for tw
		LibUsb_WriteToASIC(0xA0A, 0x1); // first frame for sz
		break;
	case 0x86:
		LibUsb_WriteToASIC(0xA00, 0x1); // first frame for tw
		LibUsb_WriteToASIC(0xA0A, 0x1); // first frame for sz
		break;
	default:
		break;
	}
	if (TRUE != LibUsb_DisableSerialFlashWriteProtect(sft))
	{
		gEC = EC_DisableFlashWriteProtectFail;
		return FALSE;
	}
	if (TRUE != LibUsb_SerialFlashErase(sft))
	{
		gEC = EC_EraseFlashFail;
		return FALSE;
	}
	sleep(1);

	//erase check
	LONG i;
	LONG fwLen = lFwLength;
	BYTE data[8];
	BYTE temp[8];
	memset(temp, 0xFF, sizeof(temp));
	for (i = 0; i < fwLen - 1024; i += 1024){
		memset(&data, 0xff, 8);
		if (!LibUsb_ReadDataFormFlash(i, data, 8))
			return FALSE;
		if (0 != memcmp(data, temp, 8))
		{
			gEC = EC_EraseFlashFail;
			return FALSE;
		}
	}

	/*********************************************************************************/
	/*********************************************************************************/
	/* 将0x160位置的四个字节设置为0xFF,在烧录固件过程中拔掉设备后，在插上设备
	dsp首先检查0x160是否是有效数据，如果是0xFF则固件无效，使用dsp rom内的固
	件启动设备，否则加载flash里面的固件启动设备。*/
	BYTE *pCopyFW = (BYTE*)malloc(lFwLength);
	if (!pCopyFW)
	{
		gEC = EC_MallocMemoryFail;
		return FALSE;
	}
	memcpy(pCopyFW, pFwBuffer, lFwLength);
	BYTE intBuffer[8] = { 0 };
	memcpy(intBuffer, pCopyFW + 0x160, 8);
	memset(pCopyFW + 0x160, 0xFF, 4);

	//259断电保护
	BYTE intBuffer_259_P1[2] = { 0 };
	BYTE intBuffer_259_P2[2] = { 0 };
	BYTE intBuffer_259_P3[21] = { 0 };
	if (chipID == 0x16)
	{
		memcpy(intBuffer_259_P1, pCopyFW, 2);
		memcpy(intBuffer_259_P2, pCopyFW + 0x6700, 2);
		memcpy(intBuffer_259_P3, pCopyFW + 0x6702, 0x15);
		memset(pCopyFW, 0xFF, 2);
		memset(pCopyFW + 0x6700, 0xFF, 0x17);
	}
	/*********************************************************************************/
	/*********************************************************************************/


	float gProgress = 0;
	for (i = 0; i < fwLen; i += 8){
		if (setProgress && ((i % 0x200) == 0))
		{
			gProgress = (float)i / (float)fwLen;
			if (bFullCheckFW)
				gProgress *= 0.5f;
			setProgress(ptrClass, gProgress);
		}
		memset(data, 0xff, 8);
		memcpy(data, pCopyFW + i, 8);
		if (!LibUsb_WriteDataToFlash(i, data, 8)){
			SAFE_DELETE_ARRAY(pCopyFW);
			return FALSE;
		}

	}

	/*********************************************************************************/
	/*********************************************************************************/
	/*烧录完成，恢复0x160地址数据*/
	if (!LibUsb_WriteDataToFlash(0x160, intBuffer, 8)){
		SAFE_DELETE_ARRAY(pCopyFW);
		return FALSE;
	}
	memcpy(pCopyFW + 0x160, intBuffer, 8);

	//259断电保护
	if (chipID == 0x16)
	{
		if (!LibUsb_WriteDataToFlash(0x6702, intBuffer_259_P3, 8)){
			SAFE_DELETE_ARRAY(pCopyFW);
			return FALSE;
		}
		if (!LibUsb_WriteDataToFlash(0x6702 + 8, intBuffer_259_P3 + 8, 8)){
			SAFE_DELETE_ARRAY(pCopyFW);
			return FALSE;
		}
		if (!LibUsb_WriteDataToFlash(0x6702 + 16, intBuffer_259_P3 + 16, 5)){
			SAFE_DELETE_ARRAY(pCopyFW);
			return FALSE;
		}


		if (!LibUsb_WriteDataToFlash(0, intBuffer_259_P1, 2)){
			SAFE_DELETE_ARRAY(pCopyFW);
			return FALSE;
		}

		if (!LibUsb_WriteDataToFlash(0x6700, intBuffer_259_P2, 2)){
			SAFE_DELETE_ARRAY(pCopyFW);
			return FALSE;
		}

		memcpy(pCopyFW, intBuffer_259_P1, 2);
		memcpy(pCopyFW + 0x6700, intBuffer_259_P2, 2);
		memcpy(pCopyFW + 0x6702, intBuffer_259_P3, 0x15);
	}
	/*********************************************************************************/
	/*********************************************************************************/


	if (bFullCheckFW)
	{
		if (setProgress)
			setProgress(ptrClass, 0.5f);
	}
	else
	{
		if(setProgress)
			setProgress(ptrClass, 1.0f);
	}

	LONG step = 1024;
	if (bFullCheckFW)
		step = 8;
	for (i = 0; i < fwLen; i += step){
		memset(&data, 0xff, 8);
		if (!LibUsb_ReadDataFormFlash(i, data, 8)){
			SAFE_DELETE_ARRAY(pCopyFW);
			return FALSE;
		}
		if (0 != memcmp(data, pCopyFW + i, 8))
		{
			gEC = EC_BurnerCheckFail;
			SAFE_DELETE_ARRAY(pCopyFW);
			return FALSE;
		}
		if (bFullCheckFW && setProgress && ((i % 0x200) == 0))
		{
			gProgress = ((float)i / (float)fwLen) * 0.5;
			gProgress += 0.5f;
			setProgress(ptrClass, gProgress);
		}
	}
	if (bFullCheckFW)
	{
		if (setProgress)
			setProgress(ptrClass, 1.0f);
	}
	return TRUE;
}

bool  SonixCam_WriteFwToFlash(unsigned char pFwBuffer[], LONG lFwLength, SonixCam_SetProgress setProgress, void *ptrClass, BOOL bFullCheckFW)
{
	if (!camera_init)
		return FALSE;

	BYTE chipID;
	DSP_ARCH_TYPE asicArchType;
	DSP_ROM_TYPE romType = LibUsb_GetChipRomType(&chipID, &asicArchType);
	if (romType == DRT_Unknow)
		return FALSE;
	switch (chipID)
	{
	case 0x85:
		LibUsb_WriteToASIC(0x5FF, 0x5A);
		LibUsb_WriteToASIC(0xA00, 0x1); // first frame for tw
		LibUsb_WriteToASIC(0xA0A, 0x1); // first frame for sz
		break;
	case 0x86:
		LibUsb_WriteToASIC(0xA00, 0x1); // first frame for tw
		LibUsb_WriteToASIC(0xA0A, 0x1); // first frame for sz
		break;
	default:
		break;
	}

	/*********************************************************************************/
	/*********************************************************************************/
	/* 将0x160位置的四个字节设置为0xFF,在烧录固件过程中拔掉设备后，在插上设备
	dsp首先检查0x160是否是有效数据，如果是0xFF则固件无效，使用dsp rom内的固
	件启动设备，否则加载flash里面的固件启动设备。*/
	BYTE *pCopyFW = (BYTE*)malloc(lFwLength);
	LONG fwLen = lFwLength;
	if (!pCopyFW)
	{
		gEC = EC_MallocMemoryFail;
		return FALSE;
	}
	memcpy(pCopyFW, pFwBuffer, lFwLength);
	BYTE intBuffer[8] = { 0 };
	memcpy(intBuffer, pCopyFW + 0x160, 8);
	memset(pCopyFW + 0x160, 0xFF, 4);

	//259断电保护
	BYTE intBuffer_259_P1[2] = { 0 };
	BYTE intBuffer_259_P2[2] = { 0 };
	BYTE intBuffer_259_P3[21] = { 0 };
	if (chipID == 0x16)
	{
		memcpy(intBuffer_259_P1, pCopyFW, 2);
		memcpy(intBuffer_259_P2, pCopyFW + 0x6700, 2);
		memcpy(intBuffer_259_P3, pCopyFW + 0x6702, 0x15);
		memset(pCopyFW, 0xFF, 2);
		memset(pCopyFW + 0x6700, 0xFF, 0x17);
	}
	/*********************************************************************************/
	/*********************************************************************************/

	float gProgress = 0;
	int i = 0;
	BYTE data[8];
	for (i = 0; i < fwLen; i += 8){
		if (setProgress && ((i % 0x200) == 0))
		{
			gProgress = (float)i / (float)fwLen;
			if (bFullCheckFW)
				gProgress *= 0.5f;
			setProgress(ptrClass, gProgress);
		}
		memset(data, 0xff, 8);
		memcpy(data, pCopyFW + i, 8);
		if (!LibUsb_WriteDataToFlash(i, data, 8)){
			SAFE_DELETE_ARRAY(pCopyFW);
			return FALSE;
		}

	}

	/*********************************************************************************/
	/*********************************************************************************/
	/*烧录完成，恢复0x160地址数据*/
	if (!LibUsb_WriteDataToFlash(0x160, intBuffer, 8)){
		SAFE_DELETE_ARRAY(pCopyFW);
		return FALSE;
	}
	memcpy(pCopyFW + 0x160, intBuffer, 8);

	//259断电保护
	if (chipID == 0x16)
	{
		if (!LibUsb_WriteDataToFlash(0x6702, intBuffer_259_P3, 8)){
			SAFE_DELETE_ARRAY(pCopyFW);
			return FALSE;
		}
		if (!LibUsb_WriteDataToFlash(0x6702 + 8, intBuffer_259_P3 + 8, 8)){
			SAFE_DELETE_ARRAY(pCopyFW);
			return FALSE;
		}
		if (!LibUsb_WriteDataToFlash(0x6702 + 16, intBuffer_259_P3 + 16, 5)){
			SAFE_DELETE_ARRAY(pCopyFW);
			return FALSE;
		}


		if (!LibUsb_WriteDataToFlash(0, intBuffer_259_P1, 2)){
			SAFE_DELETE_ARRAY(pCopyFW);
			return FALSE;
		}

		if (!LibUsb_WriteDataToFlash(0x6700, intBuffer_259_P2, 2)){
			SAFE_DELETE_ARRAY(pCopyFW);
			return FALSE;
		}

		memcpy(pCopyFW, intBuffer_259_P1, 2);
		memcpy(pCopyFW + 0x6700, intBuffer_259_P2, 2);
		memcpy(pCopyFW + 0x6702, intBuffer_259_P3, 0x15);
	}
	/*********************************************************************************/
	/*********************************************************************************/

	if (bFullCheckFW)
	{
		if (setProgress)
			setProgress(ptrClass, 0.5f);
	}
	else
	{
		if(setProgress)
			setProgress(ptrClass, 1.0f);
	}

	LONG step = 1024;
	if (bFullCheckFW)
		step = 8;
	for (i = 0; i < fwLen; i += step){
		memset(&data, 0xff, 8);
		if (!LibUsb_ReadDataFormFlash(i, data, 8)){
			SAFE_DELETE_ARRAY(pCopyFW);
			return FALSE;
		}
		if (0 != memcmp(data, pCopyFW + i, 8))
		{
			gEC = EC_BurnerCheckFail;
			SAFE_DELETE_ARRAY(pCopyFW);
			return FALSE;
		}
		if (bFullCheckFW && setProgress && ((i % 0x200) == 0))
		{
			gProgress = ((float)i / (float)fwLen) * 0.5;
			gProgress += 0.5f;
			setProgress(ptrClass, gProgress);
		}
	}
	if (bFullCheckFW)
	{
		if (setProgress)
			setProgress(ptrClass, 1.0f);
	}
	return TRUE;
}

bool SonixCam_ExportFW(unsigned char pFwBuffer[], LONG lFwLength, SonixCam_SetProgress setProgress, void *ptrClass)
{
	if (!camera_init)
		return FALSE;

	BYTE tempData[8];
	BYTE* pFw = pFwBuffer;
	LONG fwLen = lFwLength;
	BOOL sf_hight_addr = FALSE;
	BYTE addrLow, addrHigh;
	float gProgress = 0.0;  //(0.0 - 1.0)
	LONG i;
	for ( i= 0; i < fwLen; i += 8){
		if (setProgress)
		{
			gProgress = (float)i / (float)fwLen;
			//setProgress(ptrClass, gProgress);
		}
		memset(&tempData, 0xff, 8);
		if (TRUE != LibUsb_ReadDataFormFlash(i, tempData, 8))
			return FALSE;

		*(pFw + i) = tempData[0];
		*(pFw + i + 1) = tempData[1];
		*(pFw + i + 2) = tempData[2];
		*(pFw + i + 3) = tempData[3];
		*(pFw + i + 4) = tempData[4];
		*(pFw + i + 5) = tempData[5];
		*(pFw + i + 6) = tempData[6];
		*(pFw + i + 7) = tempData[7];
	}
	sf_hight_addr = FALSE;
	return TRUE;
}

BOOL SetParamToParamBuffer(BYTE paramBuffer[], LONG paramAddr, BYTE param[], LONG length)
{
	BYTE *pParamTable = paramBuffer + paramAddr;
	memset(pParamTable, 0xFF, 64);
	pParamTable[0] = length * 2 + 2;
	pParamTable[1] = 0x03;
	LONG i = 0;
	for (i = 0; i < length; i++)
	{
		*(pParamTable + 2 + 2 * i) = param[i];
		*(pParamTable + 2 + 2 * i + 1) = 0x0;
	}
	return TRUE;
}

BOOL CheckCRC(BYTE *pFW, LONG paraTableStartAddr, LONG paraTableLength, LONG crcStartAddr)
{
	USHORT crc16 = 0xFFFF;
	BYTE temp;
	LONG i, j;
	BYTE *pParaBuffer = pFW + paraTableStartAddr;
	for (i = 0; i < paraTableLength; i++)
	{
		temp = pParaBuffer[i];
		crc16 ^= temp;
		for (j = 0; j < 8; j++)
		{
			if (crc16 & 0x01)
			{
				crc16 >>= 1;
				crc16 ^= 0xA001;
			}
			else
				crc16 >>= 1;
		}
	}
	*(pFW + crcStartAddr + 20) = crc16 >> 8;
	*(pFW + crcStartAddr + 21) = crc16;
	return TRUE;
}

bool SonixCam_CustomBurnerFW(const ChangeParamInfo paramInfo, unsigned char pFwBuffer[], LONG lFwLength, SonixCam_SetProgress setProgress, void *ptrClass, SERIAL_FLASH_TYPE sft, BOOL bFullCheckFW)
{
	if (!camera_init)
		return FALSE;

	if (sft == SFT_UNKNOW)
	{
		gEC = EC_UnKnowSerialFlashType;
		return FALSE;
	}

	DWORD dwStringAddr = 0;
	ULONG dwParaTableStartAddr = 0;
	ULONG dwParaTableEndAddr = 0;
	ULONG dwCRCStartAddr = 0;

	if (!LibUsb_GetParaTableAndCRCAddrFormFW(pFwBuffer, &dwParaTableStartAddr, &dwParaTableEndAddr, &dwCRCStartAddr))
		return FALSE;

	LONG fwLen = lFwLength;
	BYTE *pCopyFW = (BYTE*)malloc(lFwLength);
	fwLen = lFwLength;
	if (!pCopyFW)
	{
		gEC = EC_MallocMemoryFail;
		return FALSE;
	}
	memcpy(pCopyFW, pFwBuffer, lFwLength);

	BYTE data[8];
	BYTE temp[8];
	LONG addIndex = 0;
	float gProgress = 0.0;  //(0.0 - 1.0)

	if (paramInfo.pVidPid)
	{
		memcpy(pCopyFW + (dwParaTableStartAddr + 0x06), paramInfo.pVidPid, 4);
	}
	if (paramInfo.pProduct)
	{
		SetParamToParamBuffer(pCopyFW, (dwParaTableStartAddr + 0x40), (BYTE*)paramInfo.pProduct, paramInfo.ProductLength);
	}
	if (paramInfo.pManufacture)
	{
		SetParamToParamBuffer(pCopyFW, (dwParaTableStartAddr + 0x80), (BYTE*)paramInfo.pManufacture, paramInfo.ManufactureLength);
	}
	if (paramInfo.pSerialNumber)
	{
		SetParamToParamBuffer(pCopyFW, (dwParaTableStartAddr + 0xC0), (BYTE*)paramInfo.pSerialNumber, paramInfo.SerialNumberLength);
	}
	if (paramInfo.pString3)
	{
		SetParamToParamBuffer(pCopyFW, (dwParaTableStartAddr + 0x100), (BYTE*)paramInfo.pString3, paramInfo.String3Length);
	}
	if (paramInfo.pInterface)
	{
		SetParamToParamBuffer(pCopyFW, (dwParaTableStartAddr + 0x140), (BYTE*)paramInfo.pInterface, paramInfo.InterfaceLength);
	}

	//CRC Check
	CheckCRC(pCopyFW, dwParaTableStartAddr, dwParaTableEndAddr - dwParaTableStartAddr, dwCRCStartAddr);


	//在285DSP的一些固件中，由于有上电直接开启图像，而开启图形无法烧录，所有要先
	//关闭图像，然后在烧录。
	BYTE chipID;
	DSP_ARCH_TYPE asicArchType;
	DSP_ROM_TYPE romType = LibUsb_GetChipRomType(&chipID, &asicArchType);
	if (romType == DRT_Unknow){
		SAFE_DELETE_ARRAY(pCopyFW);
		return FALSE;
	}
	switch (chipID)
	{
	case 0x85:
		LibUsb_WriteToASIC(0x5FF, 0x5A);
		LibUsb_WriteToASIC(0xA00, 0x1); // first frame for tw
		LibUsb_WriteToASIC(0xA0A, 0x1); // first frame for sz
		break;
	case 0x86:
		LibUsb_WriteToASIC(0xA00, 0x1); // first frame for tw
		LibUsb_WriteToASIC(0xA0A, 0x1); // first frame for sz
		break;
	default:
		break;
	}

	//Diable flash wirte protect
	if (!LibUsb_DisableSerialFlashWriteProtect(sft))
	{
		gEC = EC_DisableFlashWriteProtectFail;
		return FALSE;
	}

	//erase flash
	if (!LibUsb_SerialFlashErase(sft))
	{
		gEC = EC_EraseFlashFail;
		return FALSE;
	}
	sleep(1);

	LONG i = 0;
	//erase check
	memset(temp, 0xFF, sizeof(temp));
	for (i = 0; i < fwLen - 1024; i += 1024){
		memset(&data, 0xff, 8);
		if (!LibUsb_ReadDataFormFlash(i, data, 8))
			return FALSE;
		if (0 != memcmp(data, temp, 8))
		{
			gEC = EC_EraseFlashFail;
			return FALSE;
		}
	}

	/*********************************************************************************/
	/*********************************************************************************/
	/* 将0x160位置的四个字节设置为0xFF,在烧录固件过程中拔掉设备后，在插上设备
	dsp首先检查0x160是否是有效数据，如果是0xFF则固件无效，使用dsp rom内的固
	件启动设备，否则加载flash里面的固件启动设备。*/
	BYTE intBuffer[8] = { 0 };
	memcpy(intBuffer, pCopyFW + 0x160, 8);
	memset(pCopyFW + 0x160, 0xFF, 4);

	//259断电保护
	BYTE intBuffer_259_P1[2] = { 0 };
	BYTE intBuffer_259_P2[2] = { 0 };
	BYTE intBuffer_259_P3[21] = { 0 };
	if (chipID == 0x16)
	{
		memcpy(intBuffer_259_P1, pCopyFW, 2);
		memcpy(intBuffer_259_P2, pCopyFW + 0x6700, 2);
		memcpy(intBuffer_259_P3, pCopyFW + 0x6702, 0x15);
		memset(pCopyFW, 0xFF, 2);
		memset(pCopyFW + 0x6700, 0xFF, 0x17);
	}
	/*********************************************************************************/
	/*********************************************************************************/

	BYTE* pFw = pCopyFW;
	for (i = 0; i < fwLen; i += 8){
		if (setProgress && ((i % 0x200) == 0))
		{
			gProgress = (float)i / (float)fwLen;
			if (bFullCheckFW)
				gProgress *= 0.5f;
			setProgress(ptrClass, gProgress);
		}
		memset(data, 0xff, 8);
		memcpy(data, pFw + i, 8);
		if (!LibUsb_WriteDataToFlash(i, data, 8)){
			SAFE_DELETE_ARRAY(pCopyFW);
			return FALSE;
		}
	}


		/*********************************************************************************/
	/*********************************************************************************/
	/*烧录完成，恢复0x160地址数据*/
	if (!LibUsb_WriteDataToFlash(0x160, intBuffer, 8)){
		SAFE_DELETE_ARRAY(pCopyFW);
		return FALSE;
	}
	memcpy(pCopyFW + 0x160, intBuffer, 8);

	//259断电保护
	if (chipID == 0x16)
	{
		if (!LibUsb_WriteDataToFlash(0x6702, intBuffer_259_P3, 8)){
			SAFE_DELETE_ARRAY(pCopyFW);
			return FALSE;
		}
		if (!LibUsb_WriteDataToFlash(0x6702 + 8, intBuffer_259_P3 + 8, 8)){
			SAFE_DELETE_ARRAY(pCopyFW);
			return FALSE;
		}
		if (!LibUsb_WriteDataToFlash(0x6702 + 16, intBuffer_259_P3 + 16, 5)){
			SAFE_DELETE_ARRAY(pCopyFW);
			return FALSE;
		}

		if (!LibUsb_WriteDataToFlash(0, intBuffer_259_P1, 2)){
			SAFE_DELETE_ARRAY(pCopyFW);
			return FALSE;
		}

		if (!LibUsb_WriteDataToFlash(0x6700, intBuffer_259_P2, 2)){
			SAFE_DELETE_ARRAY(pCopyFW);
			return FALSE;
		}

		memcpy(pCopyFW, intBuffer_259_P1, 2);
		memcpy(pCopyFW + 0x6700, intBuffer_259_P2, 2);
		memcpy(pCopyFW + 0x6702, intBuffer_259_P3, 0x15);
	}
	/*********************************************************************************/
	/*********************************************************************************/

	if (bFullCheckFW)
	{
		if (setProgress)
			setProgress(ptrClass, 0.5f);
	}
	else
	{
		if (setProgress)
			setProgress(ptrClass, 1.0f);
	}

	LONG step = 1024;
	if (bFullCheckFW)
		step = 8;
	for (i = 0; i < fwLen; i += step)
	{
		memset(&data, 0xff, 8);
		if (!LibUsb_ReadDataFormFlash(i, data, 8)){
			SAFE_DELETE_ARRAY(pCopyFW);
			return FALSE;
		}
		if (0 != memcmp(data, pCopyFW + i, 8))
		{
			gEC = EC_BurnerCheckFail;
			SAFE_DELETE_ARRAY(pCopyFW);
			return FALSE;
		}
		if (bFullCheckFW && setProgress && ((i % 0x200) == 0))
		{
			gProgress = ((float)i / (float)fwLen) * 0.5;
			gProgress += 0.5f;
			setProgress(ptrClass, gProgress);
		}
	}
	if (bFullCheckFW)
	{
		if (setProgress)
			setProgress(ptrClass, 1.0f);
	}
	SAFE_DELETE_ARRAY(pCopyFW);
	return TRUE;
}

bool SonixCam_SetParamTableFormFWFile(unsigned char pFW[], long lFwLength, const ChangeParamInfo *pParamInfo, SonixCam_SetProgress setProgress, void *ptrClass, SERIAL_FLASH_TYPE sft, char* pLogFilePath)
{
	if (!camera_init)
		return false;

	if (sft == SFT_UNKNOW)
	{
		gEC = EC_UnKnowSerialFlashType;
		return false;
	}

	DWORD dwStringAddr = 0;
	ULONG dwParaTableStartAddr = 0;
	ULONG dwParaTableEndAddr = 0;
	ULONG dwCRCStartAddr = 0;
	if (!LibUsb_GetParaTableAndCRCAddrFormSF(&dwParaTableStartAddr, &dwParaTableEndAddr, &dwCRCStartAddr))
		return false;

	printf("dwParaTableStartAddr :%x, dwParaTableEndAddr : %x, dwCRCStartAddr: %x", (int)dwParaTableStartAddr, (int)dwParaTableEndAddr, (int)dwCRCStartAddr);
	LONG SZ_4K = 4 * 1024;
	LONG SZ_16K = 16 * 1024; 
	LONG SEA_4K = dwParaTableStartAddr / SZ_4K * SZ_4K;
	LONG SEA_16K = dwParaTableStartAddr / SZ_16K * SZ_16K;

	LONG startSectorEraseAddr = SEA_4K < SEA_16K ? SEA_4K : SEA_16K;
	LONG sectorEraseEndAddr = startSectorEraseAddr + SZ_16K;

	BYTE *pCopyFW = 0;
	pCopyFW = malloc(lFwLength);
	if (!pCopyFW)
		return false;
	memcpy(pCopyFW, pFW, lFwLength);

	LONG startAddr = startSectorEraseAddr;
	BOOL sf_hight_addr = FALSE;
	BYTE temp[8];
	BYTE addrLow;
	BYTE addrHigh;
	LONG addIndex = 0;
	float gProgress = 0.0;  //(0.0 - 1.0)

	if (pParamInfo->pVidPid)
	{
		BYTE *pBuffer = pCopyFW + (dwParaTableStartAddr + 0x06);
		memcpy(pBuffer, pParamInfo->pVidPid, 4);
	}
	if (pParamInfo->pProduct)
	{
		SetParamToParamBuffer(pCopyFW, (dwParaTableStartAddr + 0x40), (BYTE*)pParamInfo->pProduct, pParamInfo->ProductLength);
	}
	if (pParamInfo->pSerialNumber)
	{
		SetParamToParamBuffer(pCopyFW, (dwParaTableStartAddr + 0xC0), (BYTE*)pParamInfo->pSerialNumber, pParamInfo->SerialNumberLength);
	}
	if (pParamInfo->pManufacture)
	{
		SetParamToParamBuffer(pCopyFW, (dwParaTableStartAddr + 0x80), (BYTE*)pParamInfo->pManufacture, pParamInfo->ManufactureLength);
	}
	if (pParamInfo->pString3)
	{
		SetParamToParamBuffer(pCopyFW, (dwParaTableStartAddr + 0x100), (BYTE*)pParamInfo->pString3, pParamInfo->String3Length);
	}
	if (pParamInfo->pInterface)
	{
		SetParamToParamBuffer(pCopyFW, (dwParaTableStartAddr + 0x140), (BYTE*)pParamInfo->pInterface, pParamInfo->InterfaceLength);
	}

	//CRC Check
	CheckCRC(pCopyFW, dwParaTableStartAddr, dwParaTableEndAddr - dwParaTableStartAddr, dwCRCStartAddr);

	//disable flash write protect
	if (!LibUsb_DisableSerialFlashWriteProtect(sft))
	{
		gEC = EC_DisableFlashWriteProtectFail;
		free(pCopyFW);
		return false;
	}

	//sector erase
	LibUsb_EraseSectorForSerialFlash(dwParaTableStartAddr, (SERIAL_FLASH_TYPE)sft);
	sleep(1);
	bool bNeedEraseCrcSec = false;
	if(dwCRCStartAddr < SEA_4K || dwCRCStartAddr > (SEA_4K + SZ_4K)) //need erase crc sector
	{
		bNeedEraseCrcSec = TRUE;
		LibUsb_EraseSectorForSerialFlash(dwCRCStartAddr / SZ_4K * SZ_4K, (SERIAL_FLASH_TYPE)sft);
		sleep(1);
	}

	startAddr = startSectorEraseAddr;
	sf_hight_addr = FALSE;
	LONG flashSectorSize = SZ_16K;
	BOOL eraseCheckArr[4] = { 0 };
	//erase check and get flash sector size
	LONG i = 0;
	for (i = 0; i < SZ_16K; i += 0x50)
	{
		memset(&temp, 0xff, 8);
		if(!LibUsb_ReadDataFormFlash(startAddr, temp, 8)){
			free(pCopyFW);
			return false;
		}
		if (temp[0] != 0xFF || temp[1] != 0xFF ||
			temp[2] != 0xFF || temp[3] != 0xFF ||
			temp[4] != 0xFF || temp[5] != 0xFF ||
			temp[6] != 0xFF || temp[7] != 0xFF)
		{
			BYTE index = i / SZ_4K;
			eraseCheckArr[index] = TRUE;
			i = i / SZ_4K * SZ_4K + SZ_4K - 0x50; 
			flashSectorSize -= SZ_4K;
			startAddr = startAddr / SZ_4K * SZ_4K + SZ_4K;
			continue;
		}
		startAddr += 0x50;
	}
	

	if (!flashSectorSize)
	{
		gEC = EC_EraseFlashFail;
		return false;
	}

	//burner sector src date
	BYTE *pData = pCopyFW + startSectorEraseAddr;
	startAddr = startSectorEraseAddr;
	sf_hight_addr = FALSE;
	LONG s = 0;
	for (s = 0; s < 4; s++)
	{
		if (eraseCheckArr[s])
		{
			startAddr += SZ_4K;
			pData += SZ_4K;
			continue;
		}
		for (i = 0; i < SZ_4K; i += 8)
		{
			LONG addr = s * SZ_4K + i;
			if (setProgress && addr % 0x20)
			{
				gProgress = ((float)(addr / 2)) / (float)SZ_16K + 0.5f;
				setProgress(ptrClass, gProgress);
			}
			memcpy(temp, pData, 8);
			if(!LibUsb_WriteDataToFlash(startAddr, temp, 8)){
				free(pCopyFW);
				return false;
			}
			startAddr += 8;
			pData += 8;
		}
	}

	if(bNeedEraseCrcSec)
	{
		LONG CRC_SEA_4K = dwCRCStartAddr / SZ_4K * SZ_4K;
		startAddr = CRC_SEA_4K;
		pData = pCopyFW + CRC_SEA_4K;
		for (i = 0; i < SZ_4K; i += 8)
		{
			//LONG addr = CRC_SEA_4K + i;
			//if (setProgress && addr % 0x20)
			//{
				//gProgress = ((float)(addr / 2)) / (float)SZ_16K + 0.5f;
				//setProgress(ptrClass, gProgress);
			//}
			
			if(startAddr == 0x11210){
				if(!LibUsb_ReadDataFormFlash(startAddr, temp, 8)){
					free(pCopyFW);
					return false;
				}
				printf("read 0x11210 = %x %x %x %x %x %x %x %x\n", 
					temp[0],temp[1],temp[2],temp[3],temp[4],temp[5], temp[6],temp[7]);

			}

			memcpy(temp, pData, 8);
			if(!LibUsb_WriteDataToFlash(startAddr, temp, 8)){
				free(pCopyFW);
				return false;
			}

			if(startAddr == 0x11210){
				printf("0x11210 = %x %x %x %x %x %x %x %x\n", 
					temp[0],temp[1],temp[2],temp[3],temp[4],temp[5], temp[6],temp[7]);

				if(!LibUsb_ReadDataFormFlash(startAddr, temp, 8)){
					free(pCopyFW);
					return false;
				}
				printf("read 0x11210 = %x %x %x %x %x %x %x %x\n", 
					temp[0],temp[1],temp[2],temp[3],temp[4],temp[5], temp[6],temp[7]);

			}
				
			startAddr += 8;
			pData += 8;

		}
	}

	//burn check
	startAddr = startSectorEraseAddr;
	pData = pCopyFW + startSectorEraseAddr;
	sf_hight_addr = FALSE;
	i = 0;
	for (i = 0; i < SZ_16K; i += 0x200)
	{
		memset(&temp, 0xFF, 8);
		if(!LibUsb_ReadDataFormFlash(startAddr, temp, 8)){
			free(pCopyFW);
			return false;
		}
		if (temp[0] != *(pData + i) || temp[1] != *(pData + i + 1) ||
			temp[2] != *(pData + i + 2) || temp[3] != *(pData + i + 3) ||
			temp[4] != *(pData + i + 4) || temp[5] != *(pData + i + 5) ||
			temp[6] != *(pData + i + 6) || temp[7] != *(pData + i + 7)
			)
		{
			gEC = EC_BurnerCheckFail;
			free(pCopyFW);
			return false;
		}
		startAddr += 0x200;
	}
	free(pCopyFW);
	return true;
}


